package com.ming.mallchat.common.common.utils;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ming.mallchat.common.common.domain.vo.req.CursorPageBaseReq;
import com.ming.mallchat.common.common.domain.vo.resp.CursorPageBaseResp;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;
import java.util.Optional;
import java.util.function.Consumer;

public class CursorUtils {

    public static <T> CursorPageBaseResp<T> getCursorPageByMysql(IService<T> mapper, CursorPageBaseReq req,Consumer<LambdaQueryWrapper<T>> initWrapper, SFunction<T, ?> cursorColumn) {
        //解析字段类型
        Class<?> cursorType = LambdaUtils.getCursorType(cursorColumn);
        //封装查询条件
        LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
        //使用函数式接口给外部额外添加查询条件
        initWrapper.accept(wrapper);
        if (StringUtils.isNotBlank(req.getCursor())) {
            wrapper.lt(cursorColumn, parseCursor(req.getCursor(), cursorType));
        }
        wrapper.orderByDesc(cursorColumn);
        Page<T> page = mapper.page(req.plusPage(), wrapper);
        //获取当前最后一条数据的索引作为游标
        String cursor = Optional.ofNullable(CollectionUtil.getLast(page.getRecords()))
                .map(cursorColumn)
                .map(CursorUtils::toStr)
                .orElse(null);
        //判断是否为最后一页（可以优化，每次多查一条数据判断最好一条数据是否有值，可以减少前端最后少发一次请求）
        Boolean isLast = page.getRecords().size() != req.getPageSize();
        return new CursorPageBaseResp<>(cursor,isLast,page.getRecords());
    }

    private static String toStr(Object o) {
        if (o instanceof Date) {
            return String.valueOf(((Date) o).getTime());
        }
        return o.toString();
    }

    private static Object parseCursor(String cursor, Class<?> cursorType) {
        if (Date.class.isAssignableFrom(cursorType)) {
            return new Date(Long.parseLong(cursor));
        }
        return cursor;
    }

}
